home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1999 October: Technology Seed / ADC Seed CD - October 1999.toast / FireWire / FireWire_2.0_SDK / Source / FWiX / FWiXApp / FWiXprefs.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-04-12  |  29.7 KB  |  1,150 lines  |  [TEXT/MPS ]

  1. /*
  2.     File:        FWiXprefs.c
  3.  
  4.     Contains:    Preferences dialog and initialization.
  5.  
  6.     Version:    1.0
  7.  
  8.     Written by:    Jay Lloyd
  9.     
  10.     Copyright:    © 1996-1999 by Apple Computer, Inc., all rights reserved.
  11.  
  12.     File Ownership:
  13.  
  14.         DRI:                Jay Lloyd
  15.  
  16.         Other Contact:        
  17.  
  18.         Technology:            FireWire
  19.  
  20.     Writers:
  21.  
  22.         (DCB)    Clinton Bauder
  23.         (jkl)    Jay Lloyd
  24.  
  25.     Change History (most recent first):
  26.  
  27.       <FW10>      2/2/99    DCB        Fix for new MI headers.
  28.        <FW9>    12/19/98    DCB        More cleanup for SDK.
  29.          <8>     1/15/98    jkl        Update for new headers.
  30.        <FW7>     6/19/97    jkl        Added a preference for saving the icon view.
  31.        <FW6>     6/10/97    jkl        Updated qd global name.
  32.        <FW5>     5/27/97    jkl        Corrected a problem with the receive folder being created that
  33.                                     would cause a receive folder location other than the default to
  34.                                     not get saved.
  35.        <FW4>      5/7/97    jkl        Updated data structure names.
  36.        <FW3>     4/29/97    jkl        Fixed my bbs initials to not conflict with Jim Luther.
  37.        <FW2>     4/29/97    jkl        Added a call to Handle update event to the preferences dialog
  38.                                     event filter routine.
  39.        <FW1>     3/18/97    jkl        first checked in
  40. */
  41.  
  42. #include <Files.h>
  43. #include <Dialogs.h>
  44. #include <Sound.h>
  45. #include <Resources.h>
  46. #include <StandardFile.h>
  47. #include <Script.h>
  48. #include <Aliases.h>
  49. #include <Folders.h>
  50. #include <TextUtils.h>
  51. #include <QuickDraw.h>
  52. #include <TextEdit.h>
  53. #include <Fonts.h>
  54. #if !ETO_Build
  55. #include <ControlDefinitions.h>
  56. #endif
  57.  
  58. #include "FWiX.h"
  59. #include "FWiXmain.h"
  60. #include "FWiXdrag.h"
  61. #include "FWiXprefs.h"
  62.  
  63. static FSSpec        gDeskFolderSpec;
  64. static Str255        gSelectString = "\pSelect";
  65. static Str31        gDesktopFName = "\pDesktop";
  66. static FSSpec        gSelectSpec;
  67.  
  68. extern FWXAppDataPtr        gpFWXAppData;
  69.  
  70. ////////////////////////////////////////////////////////////////////////////////
  71. //
  72. //    HandlePrefsDialog
  73. //
  74. //    Handle the Preferences dialog.
  75. //
  76. OSErr HandlePrefsDialog (void)
  77. {
  78.     DialogPtr            pDlog;
  79.     UserItemUPP            pUserDefProc;
  80.     ModalFilterUPP        pModalFilterProc;
  81.     Ptr                    pTemp;
  82.     Handle                item;
  83.     Rect                box;
  84.     SInt16                itemHit;
  85.     OSErr                err = noErr;
  86.     
  87.     pUserDefProc = NewUserItemProc(DrawDefaultButton);
  88.     if (pUserDefProc == nil)
  89.         return memFullErr;
  90.         
  91.     pModalFilterProc = NewModalFilterProc(HandlePrefsEventFilter);
  92.     if (pModalFilterProc == nil)
  93.         return memFullErr;
  94.     
  95.     // set received items folder name
  96.     ParamText(gpFWXAppData->fwixReceiveFolder.name, "\p", "\p", "\p");
  97.     
  98.     pDlog = GetNewDialog(kPrefsDlogID, nil, (WindowPtr) -1);
  99.     if (pDlog != nil) {
  100.         // get handle to default button user item and replace with draw proc
  101.         GetDialogItem(pDlog, kDefaultUserItem, &itemHit, &item, &box);
  102.         SetDialogItem(pDlog, kDefaultUserItem, itemHit,
  103.                         (Handle) pUserDefProc, &box);
  104.         SetupDialogPrefs(pDlog);
  105.         HiliteMenu(0);      // unhilight menu title
  106.         
  107.         // JKL *** select sound name
  108.         ShowWindow(pDlog);
  109.     } else
  110.         err = ResError();
  111.     
  112.     if (err == noErr)
  113.     {
  114.         do
  115.         {
  116.             ModalDialog(pModalFilterProc, &itemHit);
  117.             HandlePrefsDialogEvent(pDlog, itemHit);            
  118.         } while ((itemHit != kOKButton) && (itemHit != kCancelButton));
  119.         
  120.         HideWindow(pDlog);    
  121.         if (itemHit == kOKButton)
  122.             err = UpdateDialogPrefs(pDlog);
  123.     
  124.         // clean up dialog memory allocations
  125.         pTemp = (Ptr) GetWRefCon(pDlog);
  126.         DisposePtr(pTemp);
  127.         DisposeRoutineDescriptor(pModalFilterProc);
  128.         DisposeRoutineDescriptor(pUserDefProc);
  129.         DisposeDialog(pDlog);
  130.     }
  131.     return err;
  132. }
  133.  
  134. //////////////////////////////////////////////////////////////////////////////
  135. //
  136. //    HandlePrefsDialogEvent
  137. //
  138. //    Handle mouseDowns in dialog items
  139. //
  140. static void    HandlePrefsDialogEvent(
  141.     DialogPtr                pDlog,
  142.     SInt16                    itemHit)
  143. {
  144.     Str255                    s;
  145.     PopupPrivateDataHandle    hPopup;
  146.     RgnHandle                hRgn;
  147.     WindowPtr                curPort;
  148.     Handle                    itemHandle;
  149.     FSSpecPtr                pDropFolder;
  150.     Rect                    box;
  151.     StandardFileReply        reply;
  152.     SInt16                    itemType;
  153.     SInt16                    curVal;
  154.     SInt16                    whichSound;
  155.     SInt16                    curAttributes;
  156.  
  157.     if ((itemHit >= kFlashBox) && (itemHit <= kOpenBox))
  158.     {
  159.         GetDialogItem(pDlog, itemHit, &itemType, &itemHandle, &box);
  160.         curVal = GetControlValue((ControlHandle) itemHandle);
  161.         SetControlValue((ControlHandle) itemHandle, 1 - curVal);
  162.  
  163.         if (itemHit == kSoundBox)
  164.         {
  165.             GetDialogItem(pDlog, kSoundPopup, &itemType, &itemHandle, &box);
  166.             hPopup = (PopupPrivateDataHandle) (**((ControlHandle) itemHandle)).contrlData;
  167.     
  168.             if (curVal == 0)
  169.                 EnableItem((**hPopup).mHandle, 0);
  170.             else
  171.                 DisableItem((**hPopup).mHandle, 0);
  172.             
  173.             hRgn = NewRgn();
  174.             if (hRgn != nil)
  175.             {
  176.                 RectRgn(hRgn, &(**((ControlHandle) itemHandle)).contrlRect);
  177.                 UpdateControls(pDlog, hRgn);
  178.                 DisposeRgn(hRgn);
  179.             }
  180.             else
  181.                 DrawControls(pDlog);
  182.         }
  183.     }
  184.     else if ((itemHit >= kCancelRadio) && (itemHit <= kOverwriteRadio))
  185.     {
  186.         GetDialogItem(pDlog, kCancelRadio, &itemType, &itemHandle, &box);
  187.         if (itemHit == kCancelRadio)
  188.             SetControlValue((ControlHandle) itemHandle, 1);
  189.         else
  190.             SetControlValue((ControlHandle) itemHandle, 0);
  191.     
  192.         GetDialogItem(pDlog, kRenameRadio, &itemType, &itemHandle, &box);
  193.         if (itemHit == kRenameRadio)
  194.             SetControlValue((ControlHandle) itemHandle, 1);
  195.         else
  196.             SetControlValue((ControlHandle) itemHandle, 0);
  197.     
  198.         GetDialogItem(pDlog, kOverwriteRadio, &itemType, &itemHandle, &box);
  199.         if (itemHit == kOverwriteRadio)
  200.             SetControlValue((ControlHandle) itemHandle, 1);
  201.         else
  202.             SetControlValue((ControlHandle) itemHandle, 0);
  203.     }
  204.     else if (itemHit == kSoundPopup)
  205.     {
  206.         // if the play sound box is checked, play the sound
  207.         GetDialogItem(pDlog, kSoundBox, &itemType, &itemHandle, &box);
  208.         curVal = GetControlValue((ControlHandle) itemHandle);
  209.         if (curVal == 1)
  210.         {
  211.             GetDialogItem(pDlog, kSoundPopup, &itemType, &itemHandle, &box);
  212.             whichSound = GetControlValue((ControlHandle) itemHandle);
  213.             hPopup = (PopupPrivateDataHandle) (**((ControlHandle) itemHandle)).contrlData;    
  214.             GetMenuItemText((**hPopup).mHandle, whichSound, s);
  215.             itemHandle = GetNamedResource('snd ', s);
  216.             if (itemHandle != nil)
  217.             {
  218.                 curAttributes = GetResAttrs(itemHandle);
  219.                 if (curAttributes & resPurgeable)
  220.                     HNoPurge(itemHandle);
  221.                 SndPlay(nil, (SndListHandle) itemHandle, false);
  222.                 SetResAttrs(itemHandle, curAttributes);
  223.                 ReleaseResource(itemHandle);
  224.             }
  225.         }
  226.     }
  227.     else if (itemHit == kDropButton)
  228.     {
  229.         GetDropFolder(&reply);
  230.         if (reply.sfGood) {
  231.             pDropFolder = (FSSpecPtr) GetWRefCon(pDlog);
  232.             FSMakeFSSpec(reply.sfFile.vRefNum, reply.sfFile.parID, reply.sfFile.name, pDropFolder);
  233.             ParamText(pDropFolder->name, "\p", "\p", "\p");
  234.  
  235.             GetPort(&curPort);
  236.             SetPort(pDlog);
  237.             InvalRect(&(pDlog->portRect));
  238.             SetPort(curPort);
  239.         }
  240.     }
  241. }
  242.  
  243. //////////////////////////////////////////////////////////////////////////////
  244. //
  245. //    GetDeskFolderSpec
  246. //
  247. //    Create FSSpec for Desktop folder
  248. //
  249. static OSErr GetDeskFolderSpec(
  250.     FSSpec             *pFileSpec)
  251. {
  252.     OSErr            err;
  253.     
  254.     pFileSpec->name[0] = '\0';
  255.     err = FindFolder(kOnSystemDisk, kDesktopFolderType, kDontCreateFolder,
  256.                         &pFileSpec->vRefNum, &pFileSpec->parID);
  257.     if (err)
  258.         return err;
  259.         
  260.     err = FSMakeFSSpec(pFileSpec->vRefNum, pFileSpec->parID, pFileSpec->name,
  261.                         pFileSpec);
  262.     return err;
  263. }
  264.  
  265. //////////////////////////////////////////////////////////////////////////////
  266. //
  267. //    GetDropFolder
  268. //
  269. //    Select a fwix receive folder
  270. //
  271. static OSErr GetDropFolder (
  272.     StandardFileReply        *reply )
  273. {
  274.     FileFilterYDUPP            pMyFileFilter;
  275.     DlgHookYDUPP            pMyDlogHook;
  276.     Point                    where = {-1,-1};
  277.     OSErr                    err = noErr;
  278.     
  279.     pMyFileFilter = NewFileFilterYDProc(FilterAllFiles);
  280.     if (pMyFileFilter == nil)
  281.         return memFullErr;
  282.     pMyDlogHook = NewDlgHookYDProc(DialogHook);
  283.     if (pMyDlogHook == nil)
  284.         return memFullErr;
  285.     GetDeskFolderSpec(&gDeskFolderSpec);
  286.         
  287.     CustomGetFile(pMyFileFilter, -1, nil, reply, kCustomGetFileResID,
  288.                     where, pMyDlogHook, nil, nil, nil, reply);
  289.     
  290.     DisposeRoutineDescriptor(pMyDlogHook);
  291.     DisposeRoutineDescriptor(pMyFileFilter);
  292.     return err;
  293. }
  294.  
  295. //////////////////////////////////////////////////////////////////////////////
  296. //
  297. //    DialogHook
  298. //
  299. //    Handle custom get file dialog actions.
  300. //
  301. static pascal SInt16 DialogHook (
  302.     SInt16                    item,
  303.     DialogPtr                pDlog,
  304.     Ptr                        pMyData)
  305. {
  306.     UserItemUPP                pUserDefProc;
  307.     StandardFileReply        *reply;
  308.     FSSpec                    curSpec;
  309.     OSType                    refCon;
  310.     Handle                    hDlogItem;
  311.     Rect                    box;
  312.     SInt16                    itemHit;
  313.     static FSSpec            lastSpec;
  314.  
  315.     refCon = GetWRefCon(pDlog);
  316.     if (refCon != sfMainDialogRefCon)
  317.         return item;
  318.     
  319.     reply = (StandardFileReply *) pMyData;
  320.     
  321.     switch (item)
  322.     {
  323.         case sfHookFirstCall:
  324.             lastSpec.vRefNum = -9999;                // init to ridiculous valuesx
  325.             pUserDefProc = NewUserItemProc(DrawUserSelection);
  326.             GetDialogItem(pDlog, kCustomGetUserItem, &itemHit, &hDlogItem, &box);
  327.             SetDialogItem(pDlog, kCustomGetUserItem, itemHit, (Handle) pUserDefProc, &box);
  328.             reply->sfFile = gpFWXAppData->fwixReceiveFolder;
  329.             item = sfHookChangeSelection;
  330.             break;
  331.         
  332.         case sfHookLastCall:
  333.             GetDialogItem(pDlog, kCustomGetUserItem, &itemHit, &hDlogItem, &box);
  334.             DisposeRoutineDescriptor((UniversalProcPtr) itemHit);
  335.             break;
  336.         
  337.         case sfHookNullEvent:
  338.             if (!SameFile(&reply->sfFile, &lastSpec))
  339.             {
  340.                 curSpec = reply->sfFile;
  341.                 FSMakeFSSpec(curSpec.vRefNum, curSpec.parID, curSpec.name, &curSpec);
  342.                 GetDialogItem(pDlog, kCustomGetUserItem, &itemHit, &hDlogItem, &box);
  343.                 InvalRect(&box);
  344.                 //SetSelectButtonName(&curSpec, pDlog);
  345.                 lastSpec = reply->sfFile;
  346.                 gSelectSpec = curSpec;
  347.             }
  348.             break;
  349.  
  350.         case kSelectItem:
  351.             item = sfItemOpenButton;
  352.             break;
  353.     }    
  354.     return item;
  355. }
  356.  
  357. //////////////////////////////////////////////////////////////////////////////
  358. //
  359. //    SameFile
  360. //
  361. //    Checks two file specs to see if they are equal
  362. //
  363. static Boolean SameFile (
  364.     FSSpec                *spec1,
  365.     FSSpec                *spec2)
  366. {
  367.     if (spec1->vRefNum != spec2->vRefNum)
  368.         return false;
  369.     if (spec1->parID != spec2->parID)
  370.         return false;
  371.     if (!EqualString( spec1->name, spec2->name, false, true))
  372.         return false;
  373.     return true;
  374. }
  375.  
  376. //////////////////////////////////////////////////////////////////////////////
  377. //
  378. //    SetSelectButtonName
  379. //
  380. //    This routine gets the "Select" button from the CustomGetFile dialog and
  381. //    the filename string from the FSSpec parameter.  It set the buttons name
  382. //    to Select “filename”, truncating the filemane if needed.  The button is
  383. //    dimmed if kCanSelectDesktop is false and the FSSpec is desktop folder.
  384. static void SetSelectButtonName (
  385.     FSSpec            *spec,
  386.     DialogPtr        theDlg)
  387. {
  388.     HParamBlockRec    pb;
  389.     Handle            iHndl;
  390.     Rect            iRect;
  391.     Str63            selNameTrunc = "\p";
  392.     Str255            btnName = "\p";
  393.     SInt16            iType;
  394.     SInt16            btnWidth;
  395.     OSErr            err;
  396.     Boolean            hilited = true;
  397.     
  398.     pb.volumeParam.ioVRefNum = spec->vRefNum;
  399.     pb.volumeParam.ioNamePtr = nil;
  400.     pb.volumeParam.ioVolIndex = 0;        // use ioVRefNum only
  401.     err = PBHGetVInfoSync(&pb);
  402.     if (err == noErr) {
  403.         if ((pb.volumeParam.ioVAtrb & 0x0080) != 0) {
  404.             // volume locked by hardware
  405.             hilited = false;
  406.         } else if ((pb.volumeParam.ioVAtrb & 0x8000) != 0) {
  407.             // volume locked by software
  408.             hilited = false;
  409.         }
  410.     }
  411.  
  412.     if (SameFile(spec, &gDeskFolderSpec)) {
  413.         AppendStrToStr(selNameTrunc, gDesktopFName, 63);
  414.         hilited = kCanSelectDesktop;
  415.     } else
  416.         AppendStrToStr( selNameTrunc, spec->name, 63 ) ;
  417.     
  418.     
  419.     GetDItem(theDlg,kSelectItem,&iType,&iHndl,&iRect);
  420.     
  421.     // truncate select name to fit in button
  422.     btnWidth = iRect.right - iRect.left;
  423.     btnWidth -= StringWidth(gSelectString);
  424.     btnWidth -= StringWidth("\p “”  ");
  425.     TruncString(btnWidth, selNameTrunc, smTruncMiddle);
  426.     
  427.     // build button name string
  428.     AppendStrToStr( btnName, gSelectString, 255 ) ;
  429.     AppendStrToStr( btnName, "\p “", 255) ;
  430.     AppendStrToStr( btnName, selNameTrunc, 255) ;
  431.     AppendStrToStr( btnName, "\p”", 255) ;
  432.     
  433.     SetCTitle((ControlRef)iHndl, btnName);
  434.  
  435.     if (hilited)
  436.         HiliteControl((ControlRef)iHndl,0);
  437.     else
  438.         HiliteControl((ControlRef)iHndl,255);        
  439. }
  440.  
  441. //////////////////////////////////////////////////////////////////////////////
  442. //
  443. //    AppendStrToStr
  444. //
  445. //    Concat two strings.
  446. //
  447. static void AppendStrToStr (
  448.     StringPtr                dst,
  449.     StringPtr                src,
  450.     UInt8                    maxDstLen)
  451. {
  452.     short        offset = dst[0]+1;
  453.     short        size   = src[0];
  454.     
  455.     if ( dst[0] + src[0] > maxDstLen)            // make sure were not too big
  456.         size = maxDstLen - dst[0];                // you should return a warning here
  457.     BlockMove(src+1, dst+offset, size);
  458.     dst[0] += size;
  459. }
  460.  
  461. //////////////////////////////////////////////////////////////////////////////
  462. //
  463. //    MyFilterAllFiles
  464. //
  465. //    Removes all files from dialog box, only get directories and volumes.
  466. //
  467. static pascal Boolean FilterAllFiles (
  468.     CInfoPBPtr                pb,
  469.     Ptr                        pMyData)
  470. {
  471.     if (pb->hFileInfo.ioFlAttrib & ioDirMask)
  472.         return false;
  473.     return true;
  474. }
  475.  
  476. //////////////////////////////////////////////////////////////////////////////
  477. //
  478. //    UpdateDialogPrefs
  479. //
  480. //    After pressing OK, update settings
  481. //
  482. static OSErr UpdateDialogPrefs (
  483.     DialogPtr                pDlog)
  484. {
  485.     Handle                    itemHandle;
  486.     PopupPrivateDataHandle    hPopup;
  487.     FSSpecPtr                pNewDropFolder;
  488.     WindowDataPtr            pWinData;
  489.     RecvNodePtr                pRecvNode;
  490.     CurFileInfoPtr            pTxInfo;
  491.     Str255                    s;
  492.     Rect                    box;
  493.     UInt32                    notifyAndConflictPrefs;
  494.     SInt16                    itemType;
  495.     SInt16                    whichSound;
  496.     OSErr                    err;
  497.     
  498.     notifyAndConflictPrefs = 0;
  499.     
  500.     // Get checkbox values
  501.     GetDialogItem(pDlog, kFlashBox, &itemType, &itemHandle, &box);
  502.     if (GetControlValue((ControlHandle) itemHandle))
  503.         notifyAndConflictPrefs |= kNotifyFlash;
  504.         
  505.     GetDialogItem(pDlog, kAlertBox, &itemType, &itemHandle, &box);
  506.     if (GetControlValue((ControlHandle) itemHandle))
  507.         notifyAndConflictPrefs |= kNotifyAlert;
  508.         
  509.     GetDialogItem(pDlog, kSoundBox, &itemType, &itemHandle, &box);
  510.     if (GetControlValue((ControlHandle) itemHandle))
  511.         notifyAndConflictPrefs |= kNotifySound;
  512.         
  513.     GetDialogItem(pDlog, kOpenBox, &itemType, &itemHandle, &box);
  514.     if (GetControlValue((ControlHandle) itemHandle))
  515.         notifyAndConflictPrefs |= kNotifyOpen;
  516.     
  517.     // Get radio box values    
  518.     GetDialogItem(pDlog, kCancelRadio, &itemType, &itemHandle, &box);
  519.     if (GetControlValue((ControlHandle) itemHandle))
  520.         notifyAndConflictPrefs |= kConflictCancel;
  521.         
  522.     GetDialogItem(pDlog, kRenameRadio, &itemType, &itemHandle, &box);
  523.     if (GetControlValue((ControlHandle) itemHandle))
  524.         notifyAndConflictPrefs |= kConflictRename;
  525.         
  526.     GetDialogItem(pDlog, kOverwriteRadio, &itemType, &itemHandle, &box);
  527.     if (GetControlValue((ControlHandle) itemHandle))
  528.         notifyAndConflictPrefs |= kConflictOverwrite;
  529.         
  530.     // Update globals and resource
  531.     gpFWXAppData->fwixPrefs &= kIconView;
  532.     gpFWXAppData->fwixPrefs |= notifyAndConflictPrefs;
  533.         
  534.     // get notify sound name
  535.     GetDialogItem(pDlog, kSoundPopup, &itemType, &itemHandle, &box);
  536.     whichSound = GetControlValue((ControlHandle) itemHandle);
  537.     hPopup = (PopupPrivateDataHandle) (**((ControlHandle) itemHandle)).contrlData;    
  538.     GetMenuItemText((**hPopup).mHandle, whichSound, s);
  539.     BlockMove(s, gpFWXAppData->fwixNotifySound, s[0] + 1);
  540.         
  541.     // get drop folder and update open drop menu item and receive node records dirID
  542.     pNewDropFolder = (FSSpecPtr) GetWRefCon(pDlog);
  543.     gpFWXAppData->fwixReceiveFolder = *pNewDropFolder;
  544.     
  545.     // update menu item
  546.     GetMenuItemText(GetMenuHandle(kFileMenuID), kOpenDropMenuItem, s);
  547.     BlockMove(    gpFWXAppData->fwixReceiveFolder.name + 1,
  548.                 s + 7,
  549.                 gpFWXAppData->fwixReceiveFolder.name[0]);
  550.     s[0] = 6 + gpFWXAppData->fwixReceiveFolder.name[0] + 1;
  551.     s[s[0]] = '”';
  552.     SetMenuItemText(GetMenuHandle(kFileMenuID), kOpenDropMenuItem, s);
  553.     
  554.     // Update the drop folder in receive info records
  555.     // Traverse the node list updating each node records dir id
  556.     pWinData = (WindowDataPtr) GetWRefCon(gpFWXAppData->pSenderWindow);
  557.     
  558.     pRecvNode = pWinData->pRecvNodeList;
  559.     while (pRecvNode != nil) {
  560.         GetCurFileInfo(pRecvNode->nodeID, &pTxInfo, false);
  561.         InitRecvFolder(& (pTxInfo->curDirID));
  562.         pRecvNode = (RecvNodePtr) pRecvNode->pNextNode;
  563.     }
  564.  
  565.     // update notification record
  566.     UpdateNotification(gpFWXAppData->pNotifyRec);
  567.     
  568.     err = UpdatePrefsFile();
  569.     return err;
  570. }
  571.     
  572. OSErr UpdatePrefsFile (void)
  573. {
  574.     Handle                    h;
  575.     AliasHandle                hAlias;
  576.     SInt32                    dirID;
  577.     FSSpec                    prefsSpec;
  578.     SInt16                    vRefNum;
  579.     SInt16                    fileRefNum;
  580.     OSErr                    err;
  581.         
  582.     // write the changes to the prefs file
  583.     err = FindFolder(kOnSystemDisk, kPreferencesFolderType, kDontCreateFolder, &vRefNum, &dirID);
  584.     if (err != noErr)
  585.         return err;
  586.         
  587.     // create the preferences file if it does not exist
  588.     h = Get1Resource('STR ', kPrefsFileResourceID);
  589.     if (h == nil)
  590.         return ResError();
  591.     DetachResource(h);
  592.     HLock(h);    
  593.     err = FSMakeFSSpec(vRefNum, dirID, (ConstStr255Param) *h, &prefsSpec);
  594.     HUnlock(h);
  595.     DisposeHandle(h);
  596.     if (err == fnfErr)
  597.     {
  598.         FSpCreateResFile(&prefsSpec, 'fwfx', 'pref', smSystemScript);
  599.         err = ResError();
  600.         if (err != noErr)
  601.             return err;
  602.     }
  603.  
  604.     fileRefNum = FSpOpenResFile(&prefsSpec, fsRdWrPerm);
  605.     err = ResError();
  606.     if (err == noErr)
  607.     {
  608.         h = Get1Resource(kPrefsResourceType, kPrefsResourceID);
  609.         if (h != nil)
  610.         {
  611.             **((UInt32 **) h) = gpFWXAppData->fwixPrefs;
  612.             ChangedResource(h);
  613.             ReleaseResource(h);
  614.         }
  615.             
  616.         h = Get1Resource('STR ', kSndPrefsResourceID);
  617.         if (h != nil)
  618.         {
  619.             SetHandleSize(h, gpFWXAppData->fwixNotifySound[0] + 1);
  620.             err = MemError();
  621.             BlockMove(gpFWXAppData->fwixNotifySound, *h, gpFWXAppData->fwixNotifySound[0] + 1);
  622.             ChangedResource(h);
  623.             ReleaseResource(h);
  624.         }
  625.         
  626.         h = Get1Resource(rAliasType, kDropPrefsResourceID);
  627.         if (h != nil)
  628.         {
  629.             err = NewAliasMinimal(&gpFWXAppData->fwixReceiveFolder, (AliasHandle *) &hAlias);
  630.             SetHandleSize(h, (**hAlias).aliasSize);
  631.             BlockMove(*hAlias, *h, (**hAlias).aliasSize);
  632.             ChangedResource(h);
  633.             ReleaseResource(h);
  634.         }
  635.         CloseResFile(fileRefNum);
  636.         FlushVol(nil, vRefNum);
  637.     }
  638.     
  639.     return err;
  640. }
  641.  
  642. //////////////////////////////////////////////////////////////////////////////
  643. //
  644. //    SetupDialogPrefs
  645. //
  646. //    Initialize dialog item settings before opening
  647. //
  648. static OSErr SetupDialogPrefs (
  649.     DialogPtr                pDlog)
  650. {
  651.     Handle                    itemHandle;
  652.     FSSpecPtr                pTempReceiveFolder;
  653.     PopupPrivateDataHandle    hPopup;
  654.     Str255                    soundText;
  655.     Rect                    box;
  656.     SInt16                    itemType;
  657.     SInt16                    itemVal;
  658.     SInt16                    activeRadio;
  659.     SInt16                    numSounds;
  660.     SInt16                    soundItem;
  661.     
  662.     // setup check boxes
  663.     GetDialogItem(pDlog, kFlashBox, &itemType, &itemHandle, &box);
  664.     SetControlValue((ControlHandle) itemHandle,
  665.         (gpFWXAppData->fwixPrefs & kNotifyFlash) ? 1 : 0);
  666.         
  667.     GetDialogItem(pDlog, kAlertBox, &itemType, &itemHandle, &box);
  668.     SetControlValue((ControlHandle) itemHandle,
  669.         (gpFWXAppData->fwixPrefs & kNotifyAlert) ? 1 : 0);
  670.         
  671.     GetDialogItem(pDlog, kSoundBox, &itemType, &itemHandle, &box);
  672.     SetControlValue((ControlHandle) itemHandle,
  673.         (gpFWXAppData->fwixPrefs & kNotifySound) ? 1 : 0);
  674.         
  675.     GetDialogItem(pDlog, kOpenBox, &itemType, &itemHandle, &box);
  676.     SetControlValue((ControlHandle) itemHandle,
  677.         (gpFWXAppData->fwixPrefs & kNotifyOpen) ? 1 : 0);
  678.  
  679.     // setup radio buttons, zero them all then set the preference
  680.     GetDialogItem(pDlog, kCancelRadio, &itemType, &itemHandle, &box);
  681.     SetControlValue((ControlHandle) itemHandle, 0);
  682.         
  683.     GetDialogItem(pDlog, kRenameRadio, &itemType, &itemHandle, &box);
  684.     SetControlValue((ControlHandle) itemHandle, 0);
  685.         
  686.     GetDialogItem(pDlog, kOverwriteRadio, &itemType, &itemHandle, &box);
  687.     SetControlValue((ControlHandle) itemHandle, 0);
  688.         
  689.     activeRadio = (gpFWXAppData->fwixPrefs & 0x0F) >> 1;
  690.     GetDialogItem(pDlog, kCancelRadio + activeRadio, &itemType, &itemHandle, &box);
  691.     SetControlValue((ControlHandle) itemHandle, 1);
  692.     
  693.     // setup the sound popup
  694.     GetDialogItem(pDlog, kSoundPopup, &itemType, &itemHandle, &box);
  695.     hPopup = (PopupPrivateDataHandle) (**((ControlHandle) itemHandle)).contrlData;
  696.     
  697.     numSounds = CountMItems((**hPopup).mHandle);
  698.     for (soundItem = 1; soundItem < numSounds; soundItem++)
  699.     {
  700.         GetMenuItemText((**hPopup).mHandle, soundItem, soundText);
  701.         if (EqualString(gpFWXAppData->fwixNotifySound, soundText, true, true))
  702.             break;
  703.     }
  704.     SetControlValue((ControlHandle) itemHandle, soundItem);
  705.     
  706.     GetDialogItem(pDlog, kSoundBox, &itemType, &itemHandle, &box);
  707.     itemVal = GetControlValue((ControlHandle) itemHandle);
  708.     if (itemVal == 1)
  709.         EnableItem((**hPopup).mHandle, 0);
  710.     else
  711.         DisableItem((**hPopup).mHandle, 0);
  712.  
  713.     // setup receive folder fsspec, stored in refCon until done
  714.     pTempReceiveFolder = (FSSpecPtr) NewPtr(sizeof(FSSpec));
  715.     if (pTempReceiveFolder == nil)
  716.         return memFullErr;
  717.         
  718.     *pTempReceiveFolder = gpFWXAppData->fwixReceiveFolder;
  719.     SetWRefCon(pDlog, (SInt32) pTempReceiveFolder);
  720.     
  721.     return noErr;
  722. }
  723.  
  724. //////////////////////////////////////////////////////////////////////////////
  725. //
  726. //    HandlePrefsEventFilter
  727. //
  728. //    Handles modal dialog filter
  729. //
  730. static pascal Boolean HandlePrefsEventFilter(
  731.     DialogPtr        pDlog,
  732.     EventRecord        *pEvent,
  733.     SInt16            *itemHit)
  734. {
  735.     Handle            item;
  736.     Rect            box;
  737.     UInt32            finalTicks;
  738.     SInt16            itemType;
  739.     UInt8            key;
  740.     Boolean            handledIt;
  741.     
  742.     handledIt = false;
  743.     
  744.     switch (pEvent->what)
  745.     {
  746.         case keyDown:
  747.             key = pEvent->message & charCodeMask;
  748.             
  749.             if (key == kReturnKey || key == kEnterKey)
  750.             {
  751.                 GetDialogItem(pDlog, kOKButton, &itemType, &item, &box);
  752.                 HiliteControl((ControlHandle) item, kControlButtonPart);
  753. #if ETO_Build
  754.                 Delay(8, (long *)&finalTicks);
  755. #else
  756.                 Delay(8, &finalTicks);
  757. #endif
  758.                 HiliteControl((ControlHandle) item, 0);
  759.                 handledIt = true;
  760.                 *itemHit = kOKButton;
  761.             }
  762.             else if (((pEvent->modifiers & cmdKey) && (key == kPeriodKey)) || (key == kEscapeKey))
  763.             {
  764.                 GetDialogItem(pDlog, kCancelButton, &itemType, &item, &box);
  765.                 HiliteControl((ControlHandle) item, kControlButtonPart);
  766. #if ETO_Build
  767.                 Delay(8, (long *) &finalTicks);
  768. #else
  769.                 Delay(8, &finalTicks);
  770. #endif
  771.                 HiliteControl((ControlHandle) item, 0);
  772.                 handledIt = true;
  773.                 *itemHit = kCancelButton;
  774.             }
  775.             break;
  776.         
  777.         case nullEvent:
  778.             HandleIdle();
  779.             break;
  780.         
  781.         case updateEvt:
  782.             HandleUpdateEvent(pEvent);
  783.             break;
  784.         
  785.         case activateEvt:
  786.             break;
  787.     }
  788.     return handledIt;
  789. }
  790.  
  791. //////////////////////////////////////////////////////////////////////////////
  792. //
  793. //    DrawUserSelection
  794. //
  795. //    Draws the selected folder text.
  796. //
  797. static pascal void DrawUserSelection(
  798.     WindowPtr        theWindow,
  799.     SInt16            itemNo)
  800. {
  801.     WindowPtr        curPort;
  802.     Handle            item;
  803.     Rect            box;
  804.     SInt32            sLength = 47;
  805.     Str255            s = "Click the Select button to select the folder: “";
  806.     SInt16            itemType;
  807.     SInt16            oldFont, oldSize;
  808.     
  809.     GetDialogItem(theWindow, itemNo, &itemType, &item, &box);
  810.     GetPort(&curPort);
  811.     SetPort(theWindow);
  812.     oldFont = theWindow->txFont;
  813.     oldSize = theWindow->txSize;
  814. #if ETO_Build
  815.     TextFont(geneva);
  816. #else
  817.     TextFont(kFontIDGeneva);
  818. #endif
  819.     TextSize(9);
  820.     BlockMove(gSelectSpec.name + 1, s + 47, gSelectSpec.name[0]);
  821.     sLength += gSelectSpec.name[0];
  822.     s[sLength] = '”';
  823.     sLength++;
  824.     TETextBox(s, sLength, &box, teJustLeft);
  825.     TextFont(oldFont);
  826.     TextSize(oldSize);
  827.     SetPort(curPort);
  828. }
  829.  
  830. //////////////////////////////////////////////////////////////////////////////
  831. //
  832. //    DrawDefaultButton
  833. //
  834. //    Draws outline around default button
  835. //
  836. static pascal void DrawDefaultButton(
  837.     WindowPtr        theWindow,
  838.     SInt16            itemNo)
  839. {
  840.     WindowPtr        curPort;
  841.     Handle            item;
  842.     PenState        curPen;
  843.     Rect            box;
  844.     SInt16            itemType;
  845.     SInt16            buttonOval;
  846.     
  847.     GetDialogItem(theWindow, itemNo, &itemType, &item, &box);
  848.     GetPort(&curPort);
  849.     SetPort(theWindow);
  850.     GetPenState(&curPen);
  851.     PenNormal();
  852.  
  853.     PenPat(& qd.black);
  854.     PenSize(3, 3);
  855.     buttonOval = ((box.bottom - box.top) / 2) + 2;
  856.     FrameRoundRect(&box, buttonOval, buttonOval);
  857.  
  858.     SetPenState(& curPen);
  859.     SetPort(curPort);
  860. }
  861.  
  862. ////////////////////////////////////////////////////////////////////////////////
  863. //
  864. //    SaveWindowPos
  865. //
  866. //    Save the window position in prefs.
  867. //
  868. OSErr SaveWindowPos (
  869.     WindowPtr            pWin)
  870. {
  871.     Handle                h;
  872.     Rect                winRect;
  873.     FSSpec                prefsSpec;
  874.     SInt32                dirID;
  875.     SInt16                fileRef, volumeRef;
  876.     OSErr                err;
  877.  
  878.     winRect = (**(((WindowPeek) pWin)->contRgn)).rgnBBox;
  879.  
  880.     // find the preferences folder
  881.     err = FindFolder(kOnSystemDisk, kPreferencesFolderType, kDontCreateFolder, &volumeRef, &dirID);
  882.     if (err != noErr)
  883.         return err;
  884.     
  885.     // open the preferences file
  886.     h = Get1Resource('STR ', kPrefsFileResourceID);
  887.     if (h == nil)
  888.         return ResError();
  889.     DetachResource(h);
  890.     HLock(h);    
  891.     err = FSMakeFSSpec(volumeRef, dirID, (ConstStr255Param) *h, &prefsSpec);
  892.     HUnlock(h);
  893.     DisposeHandle(h);
  894.     if (err == noErr)
  895.     {
  896.         fileRef = FSpOpenResFile(&prefsSpec, fsRdWrPerm);
  897.         err = ResError();
  898.         
  899.         if (err == noErr)
  900.         {
  901.             // setup the preferences flags
  902.             h = Get1Resource('win ', kWinPosPrefsID);
  903.             if (h == nil)
  904.             {
  905.                 h = NewHandle(sizeof(Rect));
  906.                 **((Rect **) h) = winRect;
  907.                 AddResource(h, kWinPosPrefsType, kWinPosPrefsID, nil);
  908.                 UpdateResFile(fileRef);
  909.                 ReleaseResource(h);
  910.             }
  911.             else
  912.             {
  913.                 **((Rect **) h) = winRect;
  914.                 ChangedResource(h);
  915.                 ReleaseResource(h);
  916.             }
  917.             CloseResFile(fileRef);
  918.         }
  919.     }
  920.     return err;
  921. }
  922.  
  923. ////////////////////////////////////////////////////////////////////////////////
  924. //
  925. //    GetWindowPos
  926. //
  927. //    Retrieves the window position in prefs.
  928. //
  929. OSErr GetWindowPos (
  930.     Rect                *r)
  931. {
  932.     Handle                h;
  933.     FSSpec                prefsSpec;
  934.     SInt32                dirID;
  935.     SInt16                fileRef, volumeRef;
  936.     OSErr                err;
  937.  
  938.     // find the preferences folder
  939.     err = FindFolder(kOnSystemDisk, kPreferencesFolderType, kDontCreateFolder, &volumeRef, &dirID);
  940.     if (err != noErr)
  941.         return err;
  942.     
  943.     // open the preferences file
  944.     h = Get1Resource('STR ', kPrefsFileResourceID);
  945.     if (h == nil)
  946.         return ResError();
  947.     DetachResource(h);
  948.     HLock(h);    
  949.     err = FSMakeFSSpec(volumeRef, dirID, (ConstStr255Param) *h, &prefsSpec);
  950.     HUnlock(h);
  951.     DisposeHandle(h);
  952.     if (err == noErr)
  953.     {
  954.         fileRef = FSpOpenResFile(&prefsSpec, fsRdPerm);
  955.         err = ResError();
  956.         
  957.         if (err == noErr)
  958.         {
  959.             // setup the preferences flags
  960.             h = Get1Resource('win ', kWinPosPrefsID);
  961.             if (h == nil)
  962.             {
  963.                 err = resNotFound;
  964.             }
  965.             else
  966.             {
  967.                 *r = **((Rect **) h);
  968.                 ReleaseResource(h);
  969.             }
  970.             CloseResFile(fileRef);
  971.         }
  972.     }
  973.     return err;
  974. }
  975.  
  976. //////////////////////////////////////////////////////////////////////////////
  977. //
  978. //    InitPrefs
  979. //
  980. //    Read the preferences from the prefs file or create it if it does not exist
  981. //
  982. OSErr InitPrefs (void)
  983. {
  984.     Handle            h;
  985.     Str63            menuString;
  986.     FSSpec            prefsSpec;
  987.     SInt32            dirID;
  988.     SInt16            vRefNum;
  989.     SInt16            fileRefNum;
  990.     SInt16            oldResFile;
  991.     OSErr            err;
  992.     Boolean            needsUpdate;
  993.  
  994.     // find the preferences folder
  995.     err = FindFolder(kOnSystemDisk, kPreferencesFolderType, kDontCreateFolder, &vRefNum, &dirID);
  996.     if (err != noErr)
  997.         return err;
  998.     
  999.     // create the preferences file if it does not exist
  1000.     h = Get1Resource('STR ', kPrefsFileResourceID);
  1001.     if (h == nil)
  1002.         return ResError();
  1003.     DetachResource(h);
  1004.     HLock(h);    
  1005.     err = FSMakeFSSpec(vRefNum, dirID, (ConstStr255Param) *h, &prefsSpec);
  1006.     HUnlock(h);
  1007.     DisposeHandle(h);
  1008.     if (err == fnfErr)
  1009.     {
  1010.         FSpCreateResFile(&prefsSpec, 'fwfx', 'pref', smSystemScript);
  1011.         err = ResError();
  1012.         if (err != noErr)
  1013.             return err;
  1014.     }
  1015.  
  1016.     oldResFile = CurResFile();
  1017.     fileRefNum = FSpOpenResFile(&prefsSpec, fsRdWrPerm);
  1018.     err = ResError();
  1019.     if (err != noErr)
  1020.     {
  1021.         // file may exist but have no resource fork, create one and open it
  1022.         FSpCreateResFile(&prefsSpec, 'fwfx', 'pref', smSystemScript);
  1023.         err = ResError();
  1024.         if (err != noErr)
  1025.             return err;
  1026.         fileRefNum = FSpOpenResFile(&prefsSpec, fsRdWrPerm);
  1027.         err = ResError();
  1028.         if (err != noErr)
  1029.             return err;
  1030.     }
  1031.     
  1032.     // setup the preferences flags
  1033.     h = Get1Resource(kPrefsResourceType, kPrefsResourceID);
  1034.     if (h == nil)
  1035.     {
  1036.         h = NewHandle(4);
  1037.         **((UInt32 **) h) = gpFWXAppData->fwixPrefs = 1;
  1038.         AddResource(h, kPrefsResourceType, kPrefsResourceID, nil);
  1039.         UpdateResFile(fileRefNum);
  1040.         ReleaseResource(h);
  1041.     }
  1042.     else
  1043.     {
  1044.         gpFWXAppData->fwixPrefs = **((UInt32 **) h);
  1045.         ReleaseResource(h);
  1046.     }
  1047.     
  1048.     // setup the notification sound preferences
  1049.     h = Get1Resource('STR ', kSndPrefsResourceID);
  1050.     if (h == nil)
  1051.     {
  1052.         UseResFile(oldResFile);
  1053.         h = Get1Resource('STR ', kSndPrefsResourceID);
  1054.         if (h == nil)
  1055.             return ResError();
  1056.         DetachResource(h);
  1057.         UseResFile(fileRefNum);
  1058.         AddResource(h, 'STR ', kSndPrefsResourceID, nil);
  1059.         UpdateResFile(fileRefNum);
  1060.         BlockMove(*h, gpFWXAppData->fwixNotifySound, **h + 1);
  1061.         ReleaseResource(h);
  1062.     }
  1063.     else
  1064.     {    
  1065.         BlockMove(*h, gpFWXAppData->fwixNotifySound, **h + 1);
  1066.         ReleaseResource(h);
  1067.     }
  1068.     
  1069.     // setup receive folder
  1070.     h = Get1Resource(rAliasType, kDropPrefsResourceID);
  1071.     if (h == nil)
  1072.     {
  1073.         // retrieve receive folder name
  1074.         UseResFile(oldResFile);
  1075.         h = Get1Resource('STR ', kDropPrefsResourceID);
  1076.         if (h == nil)
  1077.             return ResError();
  1078.         FindFolder(kOnSystemDisk, kDesktopFolderType, kDontCreateFolder, &vRefNum, &dirID);
  1079.         DetachResource(h);
  1080.         HLock(h);    
  1081.         err = FSMakeFSSpec(vRefNum, dirID, (ConstStr255Param) *h, &gpFWXAppData->fwixReceiveFolder);
  1082.         if (err == fnfErr)
  1083.             err = FSpDirCreate(&gpFWXAppData->fwixReceiveFolder, smSystemScript, &dirID);
  1084.         HUnlock(h);
  1085.         DisposeHandle(h);
  1086.  
  1087.         // update the resource
  1088.         err = NewAliasMinimal(&gpFWXAppData->fwixReceiveFolder, (AliasHandle *) &h);
  1089.         UseResFile(fileRefNum);
  1090.         AddResource(h, rAliasType, kDropPrefsResourceID, nil);
  1091.         UpdateResFile(fileRefNum);
  1092.         ReleaseResource(h);
  1093.     }
  1094.     else
  1095.     {
  1096.         // got alias, try to resolve it
  1097.         DetachResource(h);
  1098.         err = ResolveAlias(nil, (AliasHandle) h, &gpFWXAppData->fwixReceiveFolder, &needsUpdate);
  1099.         if ((err != noErr) && (err != fnfErr))
  1100.         {
  1101.             // can't resolve alias, re-init receive folder preferences
  1102.             DisposeHandle(h);
  1103.             
  1104.             UseResFile(oldResFile);
  1105.             h = Get1Resource('STR ', kDropPrefsResourceID);
  1106.             if (h == nil)
  1107.                 return ResError();
  1108.             FindFolder(kOnSystemDisk, kDesktopFolderType, kDontCreateFolder, &vRefNum, &dirID);
  1109.             DetachResource(h);
  1110.             HLock(h);    
  1111.             err = FSMakeFSSpec(vRefNum, dirID, (ConstStr255Param) *h, &gpFWXAppData->fwixReceiveFolder);
  1112.             if (err == fnfErr)
  1113.                 err = noErr;
  1114.             HUnlock(h);
  1115.             DisposeHandle(h);
  1116.  
  1117.             // update the resource
  1118.             err = NewAliasMinimal(&gpFWXAppData->fwixReceiveFolder, (AliasHandle *) &h);
  1119.             UseResFile(fileRefNum);
  1120.             AddResource(h, rAliasType, kDropPrefsResourceID, nil);
  1121.             UpdateResFile(fileRefNum);
  1122.             ReleaseResource(h);
  1123.         }
  1124.         else if (needsUpdate)
  1125.         {
  1126.             AddResource(h, rAliasType, kDropPrefsResourceID, nil);
  1127.             UpdateResFile(fileRefNum);
  1128.             ReleaseResource(h);
  1129.         }
  1130.     }
  1131.     CloseResFile(fileRefNum);
  1132.     FlushVol(nil, vRefNum);
  1133.     UseResFile(oldResFile);
  1134.                         
  1135.     // make sure receive folder exists and update open receive folder menu string
  1136.     err = FSpDirCreate(&gpFWXAppData->fwixReceiveFolder, smSystemScript, &dirID);
  1137.     if (err == dupFNErr)
  1138.         err = noErr;
  1139.  
  1140.     GetMenuItemText(GetMenuHandle(kFileMenuID), kOpenDropMenuItem, menuString);
  1141.     BlockMove (gpFWXAppData->fwixReceiveFolder.name + 1,
  1142.                 menuString + 7,
  1143.                 gpFWXAppData->fwixReceiveFolder.name[0]);
  1144.     menuString[0] = 6 + gpFWXAppData->fwixReceiveFolder.name[0] + 1;
  1145.     menuString[menuString[0]] = '”';
  1146.     SetMenuItemText(GetMenuHandle(kFileMenuID), kOpenDropMenuItem, menuString);
  1147.         
  1148.     return err;
  1149. }            
  1150.